记一次 Vue CLI 项目修改打包资源输出目录

您所在的位置:网站首页 dir 输出文件路径 记一次 Vue CLI 项目修改打包资源输出目录

记一次 Vue CLI 项目修改打包资源输出目录

2023-11-28 08:28| 来源: 网络整理| 查看: 265

问题背景

某天同事在上架浙政钉应用的时候碰到个问题,Vue 项目打包默认输出资源路径的目录结构不符合上架要求,要求是输出的所有资源需要打平放在在 build 根目录下。如下示例:

打包默认输出路径的目录结构为

需要改成如下图

问题分析

项目是基于 Vue CLI 生成的 Vue 2 项目,依赖 webpack 4.x 版本。使用 Vue CLI 创建的模板项目中,通过 package.json 可以看到安装了依赖包 @vue/cli-service。

@vue/cli-service 这个包集成了一套 webpack 的默认配置,用户可以通过配置文件 vue.config.js 进行配置,通过它提供的命令 vue-cli-service,去启动本地开发服务器(vue-cli-service serve)、打包(vue-cli-service build)等。

我们知道 webpack 处理各种资源需要配置相应 loader 去做处理,我们先查看 @vue/cli-service 中 webpack 相关的默认配置,以此作为参考,然后在配置文件 vue.config.js 中添加或修改相关配置,实现我们的目的。

怎么查看 @vue/cli-service 内置的 webpack 配置呢?可以通过它提供的 inspect 命令输出 webpack 配置信息,也可通过源码查看 webpack 相关配置。

vue inspect 命令

@vue/cli-service 提供了一个 inspect 命令来审查一个 Vue CLI 项目的 webpack 配置,我们可以通过该命令将配置信息输出到 output.js 文件中。

vue inspect > output.js--mode=production # 或者 npx @vue/cli-service inspect > output.js --mode=production

相关文档:Vue CLI - 审查项目的 webpack 配置

输出的 output.js 如下图,注意它输出的并不是一个有效的 webpack 配置文件,而是一个用于审查的被序列化的格式。

从 output.js 文件中,可以看到 js、css、图片等资源输出的相关配置。

js 文件输出路径在 js 目录下;

css 文件输出路径在 css 目录下;

图片、字体等静态资源,输出路径在 img、media、fonts 目录下;

@vue/cli-service 相关源码

@vue/cli-service 中相关 webpack 配置在 lib/config 目录;涉及到的相关文件如下:

app.js 文件;里面包含 js 资源输出相关配置,可以看到默认配置输出在 js 目录下。app.js 源码

base.js 文件;里面包含静态资源相关配置,可以看到默认配置不同类型资源输出在 img、media 、fonts 目录下,使用 file-loader 、url-loader 去处理。base.js 源码

PS: 最新源码升级到 webpack 5,将这块配置抽离成了 assets.js 文件,具体见 PR:feat!: support and use webpack 5 as default; 并且不再使用 file-loader、url-loader 去处理,而是改成通过 webpack 5 的 Assets Modules 配置,静态资源内联条件由之前配置小于 4k 变成小于 8 k(webpack 5 的默认配置),具体见 PR:feat!: remove url-loader and file-loader in favor of asset modules ;

css.js 文件;里面包含 css 相关配置,可以看到默认配置输出在 css 目录下。css.js 源码

问题解决

了解了 @vue/cli-service 内置的 webpack 相关配置,接下来一个个处理问题,在配置文件 vue.config.js 修改或添加配置。

处理输出目录名为 build;通过配置项 [outputDir](https://cli.vuejs.org/zh/config/#outputdir "outputDir") 将它配置为 build 即可。

// vue.config.js module.exports = { outputDir: 'build', // ... 其他配置 }

处理 js 文件资源输出路径;默认配置是输出在 js 目录下,我们通过配置项 chainWepack 添加如下配置,也可以通过 configureWepack 配置。

// vue.config.js module.exports = { chainWebpack: (config) => { config.output .filename('[name].[hash:8].js') .chunkFilename('[name].[hash:8].js'); }, // ... 其他配置 } // 或者 module.exports = { configureWebpack: { output: { filename: "[name].[hash:8].js", chunkFilename: "[name].[hash:8].js", }, }, // ... 其他配置 }

处理 css 文件资源输出路径;默认配置是输出在 css 目录下,我们通过 css.extract 配置项添加如下配置。

// vue.config.js module.exports = { css: { extract: { filename: "[name].[hash:8].css", chunkFilename: "[name].[hash:8].css", }, }, }

处理图片等静态资源;参考内置的默认配置,添加如下配置;

webpack 4 采用如下配置

// vue.config.js with webpack 4 const filename = '[name].[hash:8].[ext]'; const genUrlLoaderOptions = (dir) => { return { limit: 4096, // use explicit fallback to avoid regression in url-loader>=1.1.0 fallback: { loader: require.resolve("file-loader"), options: { name: filename, }, }, }; }; module.exports = { chainWebpack: (config) => { config.module .rule("images") .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); // do not base64-inline SVGs. // https://github.com/facebookincubator/create-react-app/pull/1180 config.module .rule("svg") .test(/\.(svg)(\?.*)?$/) .use("file-loader") .loader(require.resolve("file-loader")) .options({ name: filename, }); config.module .rule("media") .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); config.module .rule("fonts") .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); }, };

wepack 5 采用如下配置

// vue.config.js with webpack 5 module.exports = { chainWebpack: (config) => { const filename = `[name].[hash:8].[ext]` config.module .rule("svg") .test(/\.(svg)(\?.*)?$/) // do not base64-inline SVGs. // https://github.com/facebookincubator/create-react-app/pull/1180 .set("type", "asset/resource") .set("generator", { filename, }); config.module .rule("images") .test(/\.(png|jpe?g|gif|webp|avif)(\?.*)?$/) .set("type", "asset") .set("generator", { filename, }); config.module .rule("media") .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/) .set("type", "asset") .set("generator", { filename, }); config.module .rule("fonts") .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .set("type", "asset") .set("generator", { filename, }); }, }

添加以上配置就可以解决问题了,最后汇总在配置文件 vue.config.js 添加的所有配置如下;

webpack 4 采用如下配置

// vue.config.js with webpack 4 const filename = '[name].[hash:8].[ext]'; const genUrlLoaderOptions = (dir) => { return { limit: 4096, // use explicit fallback to avoid regression in url-loader>=1.1.0 fallback: { loader: require.resolve("file-loader"), options: { name: filename, }, }, }; }; module.exports = { outputDir: 'build', css: { extract: { filename: "[name].[hash:8].css", chunkFilename: "[name].[hash:8].css", }, }, chainWebpack: (config) => { config.module .rule("images") .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); // do not base64-inline SVGs. // https://github.com/facebookincubator/create-react-app/pull/1180 config.module .rule("svg") .test(/\.(svg)(\?.*)?$/) .use("file-loader") .loader(require.resolve("file-loader")) .options({ name: filename, }); config.module .rule("media") .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); config.module .rule("fonts") .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .use("url-loader") .loader(require.resolve("url-loader")) .options(genUrlLoaderOptions()); }, }

webpack 5 采用如下配置

// vue.config.js with webpack 5 const { defineConfig } = require("@vue/cli-service"); module.exports = defineConfig({ outputDir: "build", css: { extract: { filename: "[name].[hash:8].css", chunkFilename: "[name].[hash:8].css", }, }, chainWebpack: (config) => { // js file config.output .filename('[name].[hash:8].js') .chunkFilename('[name].[hash:8].js'); const filename = `[name].[hash:8].[ext]` config.module .rule("svg") .test(/\.(svg)(\?.*)?$/) // do not base64-inline SVGs. // https://github.com/facebookincubator/create-react-app/pull/1180 .set("type", "asset/resource") .set("generator", { filename, }); config.module .rule("images") .test(/\.(png|jpe?g|gif|webp|avif)(\?.*)?$/) .set("type", "asset") .set("generator", { filename, }); config.module .rule("media") .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/) .set("type", "asset") .set("generator", { filename, }); config.module .rule("fonts") .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .set("type", "asset") .set("generator", { filename, }); }, }); 总结

首先我们需要分析下项目使用的相关工具,知道了项目是使用 Vue CLI 生成的,本地开发、打包都是基于命令 vue-cli-service,该命令是由包 @vue/cli-service 提供,从文档中了解到它是”基于 webpack 构建,并带有合理的默认配置。“,并且提供了 inspect 命令用于审查项目的 webpack 配置。接下来通过查看 inspect 命令输出的配置信息和 @vue/cli-service 源码中的有关配置,参考它的配置,然后在配置文件 vue.config.js 添加相应配置,实现修改打包输出的资源路径。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3